../../linux/quickhacks.htm#Manpagesformattedashtml. |
Interfacing forms with CGI can be gruesome. Or it can be easy. This page gives you advice and tools to make form/CGI interfacing easy.
#!/usr/bin/perl print "Content-type: text/html\n\n"; print "Output of form. Copy next line into clipboard:<P>\n"; while(<STDIN>) { chomp($_); print "$_<br>\n"; } print "Copy previous line into clipboard<P>\n"; |
Output of form. Copy next line into clipboard: OrganizationName=orgname&OrganizationType=Choose+closest+business+... Copy previous line into clipboard |
set REQUEST_METHOD=POST rem SET NEXT LINE TO LINE LENGTH OF FILE STD.IN set CONTENT_LENGTH=2795 perl myscript.cgi < std.in > testform.htm rem NEXT LINE RUNS YOUR BROWSER LOADING TESTFORM.HTM e:\nsgold3\navigator\program\netscape.exe d:\at\perl\testform.htm |
You might want to put it in a loop with an editor so you can have a continuous edit/compile/test environment.
On your machine, change the form's action from stdin.cgi to your cgi script (myscript.cgi in this example). FTP it up to the server.
Test with your browser, and troubleshoot as necessary.
chmod a+w mydirectoryOnce the file is created, the file is owned by http or whatever, not by you. You can't delete it (except with a perlscript called from a web page). However, for securities sake, once it's created, you can deny write access to the directory with
chmod a-w mydirectoryThe perlscript will still be able to write the file, because http (or whatever) owns it.
chmod a+rx hello.cgiThe first time you create this file, and any time you get a "forbidden" response.
#!/usr/bin/perl -w # PUBLIC DOMAIN, NO WARRANTEE. USE AT YOUR OWN RISK use strict; print "Content-type: text/html\n\n"; print "<html><body>\n"; print "Hello World<p>\n"; print "</html></body>\n"; |
Once you have this file running, copy it to helloform.cgi and modify
it by placing the form writing code in a subroutine. This is essential
for future building:
#!/usr/bin/perl -w # PUBLIC DOMAIN, NO WARRANTEE. USE AT YOUR OWN RISK use strict; sub MakePage() { print "Content-type: text/html\n\n"; print "<html><body>\n"; print "Hello World<br>\n"; print "</html></body>\n"; } MakePage(); |
Note that stdin.cgi was coded earlier on this page, and outputs the
form information in a raw form. Assuming you leave the field contents at
their default "Hello World", the output after you click the submit button
will appear as follows:
Output of form. Copy next line into clipboard: TXhelloField=Hello+World&BXsub=Submit Copy previous line into clipboard |
You can see that controls are separated by ampersand (&) signs,
and each control name is separated from its value by an equal sign (=).
Also evident is that spaces are represented by plus signs. What you don't
see in this example is that punctuation is represented by by a percent
sign followed by a two hex digit representation of the character's ascii
value. Place the string "<<??==%%>>" in the field, and the output
now looks like this:
Output of form. Copy next line into clipboard: TXhelloField=%3C%3C%3F%3F%3D%3D%25%25%3E%3E&BXsub=Submit Copy previous line into clipboard |
To explore the representation of various characters, copy helloform.cgi
to testchars.cgi, which is coded as follows:
#!/usr/bin/perl -w use strict; sub MakeString() { my($string) = ""; my($i); foreach $i (32..126) { $string .= chr($i) unless ($i == 34); } return($string); } sub MakePage() { print "Content-type: text/html\n\n"; print "<html><head><title>Hello World Form</title></head><body>\n"; print "<center><big><big><big><strong>\n"; print "Hello World Form<p>\n"; print "</strong></big></big></big>\n"; print "<FORM ACTION=\"./stdin.cgi\" METHOD=\"POST\">\n"; print "The Field...<br>\n"; print "<input type=\"text\" name=\"TXhelloField\" size=\"100\" \n"; print "value=\"" . MakeString() . "\">\n"; print "<INPUT type=\"submit\" name=\"BXsub\" value=\"Submit\">\n"; print "</form>"; print "</body></html>\n"; } MakePage(); |
Note the MakeString() function, which constructs a string consisting
of all characters of decimal ascii values 32 (space) to 126 (~) except
34 (>), which would interfere with the html. After pressing the submit
button, stdin.cgi shows the following output:
Output of form. Copy next line into clipboard: TXhelloField=+%21%23%24%25%26%27%28%29*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E&BXsub=Submit Copy previous line into clipboard |
Basically, digits and letters (lower and upper case) come through as themselves, spaces come through as plus signs, while all other characters come through as a percent sign (%) followed by a hex representation of the character. Remembering that form controls are separated by ampersands (&), and each control's name is separated from its value by an equal sign (=), we're ready to write a decode function.
Now add the decode function. Here's the English description of what it must do. First it must replace each plus sign with a space. Then it must replace each percent sign followed by two hex digits with the character whose ascii value is equal to the number defined by the two hex digits. Here's one way to do that.
Start with an empty return string. Split the incoming string into a
list at percent signs. If the first character of the string is a percent
sign, throw away the first list element. Otherwise copy the first element's
string into the return string, and then throw away the first element. From
this point forth, every list element's first two characters are a hex representation
of a character, so for each append that char, and then append the rest
of the element's string. Here's the code:
#!/usr/bin/perl sub decode($) { $_[0] =~ s/\+/ /g; ### Change + to space my(@parts) = split /%/, $_[0]; my($returnstring) = ""; (($_[0] =~ m/^\%/) ? (shift(@parts)) : ($returnstring = shift(@parts))); my($part); foreach $part (@parts) { $returnstring .= chr(hex(substr($part,0,2))); my($tail) = substr($part,2); $returnstring .= $tail if (defined($tail)); } return($returnstring); } print "Content-type: text/html\n\n"; print "Output of form. Copy next line into clipboard:<P>\n"; while(<STDIN>) { chomp($_); print decode($_); print "<br>\n"; } print "Copy previous line into clipboard<P>\n"; |
Notice in the preceding code that we coded the decode algorithm, and instead of printing the raw form output as in stdin.cgi, we run it through decode. The result is a string remarkably like the one typed in.
The preceding was only the lowest level of decoding. Form output inserts
ampersands (&) to delineate controls (typically form fields and buttons),
and within those controls, inserts equal signs (=) to separate the control's
name from its data. What you really want to do is to use the form's output
to populate a hash whose keys are control names and whose values are the
controls' data values. Each of the values must be run through decode in
order to
First separate the controls at the ampersands. Then for each control
create a hash entry whose key is the control's name, and whose value is
the decode of its value. The decode is simply to replace each plus sign
with a space, and for each percent sign followed by two hex digits,
substitute the ascii character whose value is that hex digit. Here's decode.cgi,
with function decode, which returns the control hash: